package com.smart.community.region.service.impl;

import java.time.LocalDateTime;
import java.util.Comparator;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.smart.community.commons.enums.SystemStatusEnum;
import com.smart.community.commons.utils.SecurityUtils;
import com.smart.community.feign.property.service.IPropertyCompanyCommunityFeign;
import com.smart.community.region.dto.ZoneDrawingSaveDTO;
import com.smart.community.region.dto.ZoneSaveRequest;
import com.smart.community.region.entity.Building;
import com.smart.community.region.entity.Zone;
import com.smart.community.region.entity.ZoneDrawing;
import com.smart.community.region.service.IBuildingService;
import com.smart.community.region.service.ICommunityService;
import com.smart.community.region.service.IZoneDrawingService;
import com.smart.community.region.service.IZoneManagementService;
import com.smart.community.region.service.IZoneService;
import com.smart.community.region.vo.CommunityEntryStateVO;
import com.smart.community.region.vo.ZoneManagementInitialDataVO;

import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;

/**
 * 分区管理服务实现类
 * 
 * @author Wu.Liang
 * @date 2025-01-30
 */
@Service
@Slf4j
public class ZoneManagementServiceImpl implements IZoneManagementService {

    @Autowired
    private IZoneService zoneService;

    @Autowired
    private IBuildingService buildingService;

    @Autowired
    private ICommunityService communityService;

    @Autowired
    private IZoneDrawingService zoneDrawingService;

    @Autowired
    private IPropertyCompanyCommunityFeign propertyCompanyCommunityFeign;

    @Override
    @Cacheable(value = "zone:management", key = "'entry-state:' + #communityId", unless = "#result == null")
    public CommunityEntryStateVO determineCommunityEntryState(Long communityId) {
        long startTime = System.currentTimeMillis();
        log.info("判断社区进入状态，社区ID: {}", communityId);
        
        // 参数验证
        if (communityId == null) {
            log.warn("社区ID不能为空");
            return null;
        }
        
        try {
            // 直接查询分区表，检查是否有分区数据
            LambdaQueryWrapper<Zone> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Zone::getCommunityId, communityId)
                       .eq(Zone::getDeleted, 0);
            List<Zone> zones = zoneService.list(queryWrapper);
            
            boolean hasExistingZones = !zones.isEmpty();
            
            // 获取最后修改时间
            String lastModifiedTime = null;
            if (hasExistingZones && !zones.isEmpty()) {
                Zone latestZone = zones.stream()
                    .max(Comparator.comparing(Zone::getUpdateTime))
                    .orElse(null);
                if (latestZone != null) {
                    lastModifiedTime = latestZone.getUpdateTime().toString();
                }
            }
            
            // 判断是否初次进入
            boolean isFirstEntry = !hasExistingZones;
            
            CommunityEntryStateVO state = new CommunityEntryStateVO();
            state.setFirstEntry(isFirstEntry);
            state.setHasExistingZones(hasExistingZones);
            state.setZoneCount(zones != null ? zones.size() : 0);
            state.setLastModifiedTime(lastModifiedTime);
            
            long endTime = System.currentTimeMillis();
            log.info("判断社区进入状态完成，社区ID: {}，初次进入: {}，分区数量: {}，耗时: {}ms", 
                    communityId, isFirstEntry, state.getZoneCount(), (endTime - startTime));
            
            return state;
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            log.warn("判断社区进入状态失败，社区ID: {}，耗时: {}ms，错误: {}", 
                    communityId, (endTime - startTime), e.getMessage());
            return null;
        }
    }

    @Override
    @Cacheable(value = "zone:management", key = "'initial-data:' + #communityId", unless = "#result == null")
    public ZoneManagementInitialDataVO getInitialData(Long communityId) {
        long startTime = System.currentTimeMillis();
        log.info("获取分区管理初始数据，社区ID: {}", communityId);
        
        // 参数验证
        if (communityId == null) {
            log.warn("社区ID不能为空");
            return null;
        }
        
        try {
            ZoneManagementInitialDataVO data = new ZoneManagementInitialDataVO();
            
            // 获取社区信息
            data.setCommunityInfo(communityService.getById(communityId));
            
            // 获取楼栋列表
            try {
                List<Building> buildings = buildingService.getBuildingsByCommunity(communityId);
                data.setBuildingList(buildings != null ? new java.util.ArrayList<>(buildings) : new java.util.ArrayList<>());
            } catch (Exception e) {
                log.warn("获取楼栋列表失败，社区ID: {}，错误: {}", communityId, e.getMessage());
                data.setBuildingList(new java.util.ArrayList<>());
            }
            
            // 获取分区列表
            LambdaQueryWrapper<Zone> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Zone::getCommunityId, communityId)
                       .eq(Zone::getDeleted, 0)
                       .orderByDesc(Zone::getSortOrder);
            List<Zone> zones = zoneService.list(queryWrapper);
            data.setZoneList(zones != null ? new java.util.ArrayList<>(zones) : new java.util.ArrayList<>());
            
            // 获取绘图数据（无论是否有分区数据都尝试加载）
            try {
                LambdaQueryWrapper<ZoneDrawing> drawingQueryWrapper = new LambdaQueryWrapper<>();
                drawingQueryWrapper.eq(ZoneDrawing::getCommunityId, communityId)
                                 .eq(ZoneDrawing::getIsCurrent, SystemStatusEnum.ENABLED.getCode())
                                 .eq(ZoneDrawing::getDeleted, 0);
                ZoneDrawing drawing = zoneDrawingService.getOne(drawingQueryWrapper);
                if (drawing != null) {
                    data.setDrawingData(drawing);
                    log.debug("绘图数据加载成功，社区ID: {}", communityId);
                } else {
                    log.debug("未找到绘图数据，社区ID: {}", communityId);
                }
            } catch (Exception e) {
                log.warn("获取绘图数据失败，社区ID: {}，错误: {}", communityId, e.getMessage());
            }
            
            long endTime = System.currentTimeMillis();
            log.info("获取分区管理初始数据完成，社区ID: {}，楼栋数量: {}，分区数量: {}，耗时: {}ms", 
                    communityId, data.getBuildingList().size(), data.getZoneList().size(), (endTime - startTime));
            
            return data;
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            log.warn("获取分区管理初始数据失败，社区ID: {}，耗时: {}ms，错误: {}", 
                    communityId, (endTime - startTime), e.getMessage());
            return null;
        }
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(value = "zone:management", allEntries = true)
    public String saveZoneData(ZoneSaveRequest request) {
        long startTime = System.currentTimeMillis();
        log.info("保存分区管理数据，社区ID: {}", request != null ? request.getCommunityId() : null);
        
        // 参数验证
        if (request == null) {
            log.warn("保存请求不能为空");
            return "保存失败：请求参数为空";
        }
        if (request.getCommunityId() == null) {
            log.warn("社区ID不能为空");
            return "保存失败：社区ID为空";
        }
        
        try {
            // 实现分区管理数据的保存逻辑
            // 这里需要保存分区管理相关数据
            // 这里需要根据具体的业务需求实现
            
            long endTime = System.currentTimeMillis();
            log.info("保存分区管理数据完成，社区ID: {}，耗时: {}ms", 
                    request.getCommunityId(), (endTime - startTime));
            
            return "保存成功";
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            log.warn("保存分区管理数据失败，社区ID: {}，耗时: {}ms，错误: {}", 
                    request.getCommunityId(), (endTime - startTime), e.getMessage());
            return "保存失败：" + e.getMessage();
        }
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(value = {"zone:drawing", "zone:management"}, allEntries = true)
    public String saveDrawingData(ZoneDrawingSaveDTO request) {
        long startTime = System.currentTimeMillis();
        log.info("保存绘图数据，社区ID: {}", request != null ? request.getCommunityId() : null);
        
        // 参数验证
        if (request == null) {
            log.warn("保存请求不能为空");
            return "保存失败：请求参数为空";
        }
        if (request.getCommunityId() == null) {
            log.warn("社区ID不能为空");
            return "保存失败：社区ID为空";
        }
        
        try {
            // 获取物业公司ID：优先使用前端传递的，如果没有则根据社区ID获取
            Long propertyCompanyId = request.getPropertyCompanyId();
            if (propertyCompanyId == null) {
                propertyCompanyId = getPropertyCompanyIdByCommunityId(request.getCommunityId());
            }
            
            // 创建新的绘图数据记录
            ZoneDrawing drawing = new ZoneDrawing();
            drawing.setCommunityId(request.getCommunityId());
            drawing.setPropertyCompanyId(propertyCompanyId);
            drawing.setDrawingData(com.alibaba.fastjson.JSON.toJSONString(request));
            drawing.setCanvasWidth(800);
            drawing.setCanvasHeight(600);
            drawing.setZoomLevel(new java.math.BigDecimal("1.0"));
            drawing.setVersion(1);
            drawing.setIsCurrent(SystemStatusEnum.ENABLED.getCode());
            // 设置创建用户信息，遵循规范
            Long currentUserId = SecurityUtils.getCurrentUserId();
            drawing.setCreateBy(currentUserId);
            drawing.setUpdateBy(currentUserId);
            LocalDateTime now = LocalDateTime.now();
            drawing.setCreateTime(now);
            drawing.setUpdateTime(now);
            
            boolean success = zoneDrawingService.save(drawing);
            long endTime = System.currentTimeMillis();
            
            if (success) {
                log.info("保存绘图数据成功，社区ID: {}，耗时: {}ms", 
                        request.getCommunityId(), (endTime - startTime));
                return "保存成功";
            } else {
                log.warn("保存绘图数据失败，社区ID: {}，耗时: {}ms", 
                        request.getCommunityId(), (endTime - startTime));
                return "保存失败：数据库操作失败";
            }
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            log.warn("保存绘图数据失败，社区ID: {}，耗时: {}ms，错误: {}", 
                    request.getCommunityId(), (endTime - startTime), e.getMessage());
            return "保存失败：" + e.getMessage();
        }
    }

    /**
     * 根据社区ID获取物业公司ID
     * 
     * @param communityId 社区ID
     * @return 物业公司ID，如果没有关联则返回null
     */
    private Long getPropertyCompanyIdByCommunityId(Long communityId) {
        try {
            // 通过Feign客户端调用物业服务获取物业公司ID
            Long propertyCompanyId = propertyCompanyCommunityFeign.getPropertyCompanyIdByCommunityId(communityId);
            if (propertyCompanyId != null) {
                log.debug("根据社区ID获取物业公司ID成功，社区ID: {}，物业公司ID: {}", communityId, propertyCompanyId);
                return propertyCompanyId;
            } else {
                log.warn("社区ID: {} 未关联任何物业公司", communityId);
                return null;
            }
        } catch (Exception e) {
            log.warn("根据社区ID获取物业公司ID失败，社区ID: {}，错误: {}", communityId, e.getMessage());
            return null;
        }
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(value = {"zone:drawing", "zone:management"}, allEntries = true)
    public String updateDrawingData(Long id, ZoneDrawingSaveDTO request) {
        long startTime = System.currentTimeMillis();
        log.info("更新绘图数据，ID: {}, 社区ID: {}", id, request != null ? request.getCommunityId() : null);
        
        // 参数验证
        if (id == null) {
            log.warn("绘图数据ID不能为空");
            return "更新失败：绘图数据ID为空";
        }
        if (request == null) {
            log.warn("更新请求不能为空");
            return "更新失败：请求参数为空";
        }
        if (request.getCommunityId() == null) {
            log.warn("社区ID不能为空");
            return "更新失败：社区ID为空";
        }
        
        try {
            // 获取现有绘图数据
            ZoneDrawing existingDrawing = zoneDrawingService.getById(id);
            if (existingDrawing == null) {
                log.warn("绘图数据不存在，ID: {}", id);
                return "更新失败：绘图数据不存在";
            }
            
            // 获取物业公司ID：优先使用前端传递的，如果没有则根据社区ID获取
            Long propertyCompanyId = request.getPropertyCompanyId();
            if (propertyCompanyId == null) {
                propertyCompanyId = getPropertyCompanyIdByCommunityId(request.getCommunityId());
                log.debug("前端未传递物业公司ID，根据社区ID获取物业公司ID，社区ID: {}，物业公司ID: {}", 
                        request.getCommunityId(), propertyCompanyId);
            }
            
            // 更新绘图数据
            existingDrawing.setDrawingData(com.alibaba.fastjson.JSON.toJSONString(request));
            existingDrawing.setPropertyCompanyId(propertyCompanyId); // 确保物业公司ID正确设置
            existingDrawing.setUpdateTime(java.time.LocalDateTime.now());
            // 设置更新用户信息，遵循规范
            existingDrawing.setUpdateBy(SecurityUtils.getCurrentUserId());
            
            boolean success = zoneDrawingService.updateById(existingDrawing);
            long endTime = System.currentTimeMillis();
            
            if (success) {
                log.info("更新绘图数据成功，ID: {}，社区ID: {}，耗时: {}ms", 
                        id, request.getCommunityId(), (endTime - startTime));
                return "更新成功";
            } else {
                log.warn("更新绘图数据失败，ID: {}，社区ID: {}，耗时: {}ms", 
                        id, request.getCommunityId(), (endTime - startTime));
                return "更新失败：数据库操作失败";
            }
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            log.warn("更新绘图数据失败，ID: {}，社区ID: {}，耗时: {}ms，错误: {}", 
                    id, request.getCommunityId(), (endTime - startTime), e.getMessage());
            return "更新失败：" + e.getMessage();
        }
    }

    @Override
    @Cacheable(value = "zone:drawing", key = "'community-data:' + #communityId", unless = "#result == null")
    public Object getCommunityDrawingData(Long communityId) {
        long startTime = System.currentTimeMillis();
        log.info("获取社区绘图数据，社区ID: {}", communityId);
        
        // 参数验证
        if (communityId == null) {
            log.warn("社区ID不能为空");
            return null;
        }
        
        try {
            LambdaQueryWrapper<ZoneDrawing> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ZoneDrawing::getCommunityId, communityId)
                       .eq(ZoneDrawing::getIsCurrent, SystemStatusEnum.ENABLED.getCode())
                       .eq(ZoneDrawing::getDeleted, 0);
            ZoneDrawing drawing = zoneDrawingService.getOne(queryWrapper);
            
            if (drawing != null) {
                // 解析绘图数据JSON并添加ID信息
                Object drawingData = com.alibaba.fastjson.JSON.parse(drawing.getDrawingData());
                
                // 如果返回的是Map类型，添加ID信息
                if (drawingData instanceof java.util.Map) {
                    @SuppressWarnings("unchecked")
                    java.util.Map<String, Object> dataMap = (java.util.Map<String, Object>) drawingData;
                    dataMap.put("id", drawing.getId());
                    dataMap.put("drawingId", drawing.getId()); // 添加drawingId字段作为备用
                    
                    long endTime = System.currentTimeMillis();
                    log.info("获取社区绘图数据成功，社区ID: {}，耗时: {}ms", 
                            communityId, (endTime - startTime));
                    return dataMap;
                }
                
                // 如果返回的是其他类型，创建一个包含ID的新Map
                java.util.Map<String, Object> result = new java.util.HashMap<>();
                result.put("id", drawing.getId());
                result.put("drawingId", drawing.getId());
                result.put("drawingData", drawingData);
                
                long endTime = System.currentTimeMillis();
                log.info("获取社区绘图数据成功，社区ID: {}，耗时: {}ms", 
                        communityId, (endTime - startTime));
                return result;
            }
            
            long endTime = System.currentTimeMillis();
            log.info("未找到社区绘图数据，社区ID: {}，耗时: {}ms", 
                    communityId, (endTime - startTime));
            return null;
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            log.warn("获取社区绘图数据失败，社区ID: {}，耗时: {}ms，错误: {}", 
                    communityId, (endTime - startTime), e.getMessage());
            return null;
        }
    }
}

